// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: ui_widget_context.cpp
// Description: UIWidgetContext Class
//      Author: Ziming Li
//     Created: 2022-03-03
// -------------------------------------------------
// Copyright (C) 2022 MingYang Software Technology.
// -------------------------------------------------

#include "./ui_widget_context.h"

#include "blinkit/blink/renderer/bindings/core/qjs/qjs_bindings.h"
#include "blinkit/blink/renderer/core/EventNames.h"
#include "blinkit/blink/renderer/core/HTMLNames.h"

namespace BlinKit {

UIWidgetContext::UIWidgetContext(LocalFrame &frame) : ScriptController(frame)
{
}

void UIWidgetContext::RegisterContainerNodePrototypes(JSContext *ctx, Prototypes &dst, JSValue protoContainerNode)
{
    using namespace qjs;

    dst.prototypes[PROTO_Document] = CreateDocumentPrototypeForUI(ctx, protoContainerNode);

    dst.prototypes[PROTO_Element] = CreateElementPrototypeForUI(ctx, protoContainerNode);
    RegisterElementPrototypes(dst.elementPrototypes, ctx, dst.prototypes[PROTO_Element]);

    dst.prototypes[PROTO_DocumentFragment] = CreateDocumentFragmentPrototype(ctx, protoContainerNode);
    dst.prototypes[PROTO_ShadowRoot] = CreateShadowRootPrototype(ctx, dst.prototypes[PROTO_DocumentFragment]);

    dst.prototypes[PROTO_StyleSheetList] = CreateStyleSheetListPrototype(ctx);
}

void UIWidgetContext::RegisterElementPrototypes(PrototypeMap &dst, JSContext *ctx, JSValue elementPrototype)
{
    using namespace HTMLNames;
    using namespace qjs;

    dst.emplace(buttonTag.localName(), CreateButtonElementPrototype(ctx, elementPrototype));
    dst.emplace(formTag.localName(), CreateFormElementPrototype(ctx, elementPrototype));
    dst.emplace(inputTag.localName(), CreateInputElementPrototype(ctx, elementPrototype));
    dst.emplace(optionTag.localName(), CreateOptionElementPrototype(ctx, elementPrototype));
    dst.emplace(progressTag.localName(), CreateProgressElementPrototype(ctx, elementPrototype));
    dst.emplace(selectTag.localName(), CreateSelectElementPrototype(ctx, elementPrototype));
    dst.emplace(textareaTag.localName(), CreateTextAreaElementPrototype(ctx, elementPrototype));
}

void UIWidgetContext::RegisterEventPrototypes(PrototypeMap &dst, JSContext *ctx, JSValue eventPrototype)
{
    using namespace EventNames;
    using namespace qjs;

    dst.emplace(CustomEvent, CreateCustomEventPrototype(ctx, eventPrototype));
    dst.emplace(EventNames::MessageEvent, CreateMessageEventPrototype(ctx, eventPrototype));

    JSValue uiEventPrototype = CreateUIEventPrototype(ctx, eventPrototype);
    dst.emplace(UIEvent, uiEventPrototype);
    dst.emplace(FocusEvent, CreateFocusEventPrototype(ctx, uiEventPrototype));
    dst.emplace(EventNames::KeyboardEvent, CreateKeyboardEventPrototype(ctx, uiEventPrototype));
    dst.emplace(MouseEvent, CreateMouseEventPrototype(ctx, uiEventPrototype));
}

void UIWidgetContext::RegisterEventTargetPrototypes(JSContext *ctx, Prototypes &dst, JSValue protoEventTarget)
{
    JSValue protoNode = qjs::CreateNodePrototypeForUI(ctx, protoEventTarget);
    RegisterNodePrototypes(ctx, dst, protoNode);
    JS_FreeValue(ctx, protoNode);
}

void UIWidgetContext::RegisterNodePrototypes(JSContext *ctx, Prototypes &dst, JSValue protoNode)
{
    using namespace qjs;

    JSValue protoContainerNode = CreateContainerNodePrototype(ctx, protoNode);
    RegisterContainerNodePrototypes(ctx, dst, protoContainerNode);
    JS_FreeValue(ctx, protoContainerNode);

    RegisterCharacterDataPrototypes(ctx, dst, protoNode);
}

void UIWidgetContext::RegisterPrototypes(JSContext *ctx, Prototypes &dst)
{
    using namespace qjs;

    dst.prototypes[PROTO_Window] = CreateWindowPrototypeForUI(ctx);

    JSValue protoEventTarget = CreateEventTargetPrototype(ctx);
    RegisterEventTargetPrototypes(ctx, dst, protoEventTarget);
    JS_FreeValue(ctx, protoEventTarget);

    RegisterEventPrototypes(dst.eventPrototypes, ctx, dst.prototypes[PROTO_Event]);

    dst.prototypes[PROTO_ClientRect] = CreateClientRectPrototype(ctx);
    dst.prototypes[PROTO_CSSStyleDeclaration] = CreateCSSStyleDeclarationPrototype(ctx);
    dst.prototypes[PROTO_Location] = CreateLocationPrototypeForUI(ctx);
    dst.prototypes[PROTO_Navigator] = CreateNavigatorPrototypeForUI(ctx);
    dst.prototypes[PROTO_Screen] = CreateScreenPrototype(ctx);
}

} // namespace BlinKit
